/**
 * 
 */
package com.letoo.dragon.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * GZIP工具。
 * 
 * @author dengjie
 *
 */
public abstract class GZipUtils {

    private static final Logger LOG = LoggerFactory.getLogger(GZipUtils.class);

    public static final int BUFFER = 2048;

    /**
     * 默认字符串编码为utf-8
     */
    private static String encode = "utf-8";

    /**
     * 字符串压缩为字节数组
     * 
     * @param str
     *            需要被GZIP压缩的字符串
     * @return 默认编码urf-8压缩后的字节数组.抛异常后返回的是null
     */
    public static byte[] compressToByte(String str) {
        if (str == null || str.length() == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = null;
        try {
            gzip = new GZIPOutputStream(out);
            gzip.write(str.getBytes(encode));
            gzip.close();
            return out.toByteArray();
        } catch (IOException e) {
            LOG.error("GZipUtils compressToByte(String str)方法抛出IO异常", e);
        } finally {
            if (gzip != null) {
                try {
                    gzip.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils compressToByte(String str)方法抛出IO异常", e);
                }
            }
        }
        return null;
    }

    /**
     * 字符串压缩为字节数组
     * 
     * @param str
     *            需要被GZIP压缩的字符串
     * @param encoding
     *            指定编码
     * @return 默认编码urf-8压缩后的字节数组.抛异常后返回的是null
     */
    public static byte[] compressToByte(String str, String encoding) {
        if (str == null || str.length() == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        GZIPOutputStream gzip = null;
        try {
            gzip = new GZIPOutputStream(out);
            gzip.write(str.getBytes(encoding));
            gzip.close();
            return out.toByteArray();
        } catch (IOException e) {
            LOG.error("GZipUtils compressToBytecompressToByte(String str, String encoding)方法抛出IO异常", e);
        } finally {
            if (gzip != null) {
                try {
                    gzip.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils compressToBytecompressToByte(String str, String encoding)方法抛出IO异常", e);
                }
            }
        }
        return null;
    }

    /**
     * 字节数组解压缩后返回字符串
     * 
     * @param b
     *            需要被解压的字节数组
     * @return 解压后的字符串。异常后返回null。
     */
    public static String uncompressToString(byte[] b) {
        if (b == null || b.length == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(b);

        try {
            GZIPInputStream gunzip = new GZIPInputStream(in);
            byte[] buffer = new byte[BUFFER];
            int n;
            while ((n = gunzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
            return out.toString(encode);
        } catch (IOException e) {
            LOG.error("GZipUtils uncompressToString(byte[] b)方法抛出IO异常", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils uncompressToString(byte[] b)方法抛出IO异常", e);
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils uncompressToString(byte[] b)方法抛出IO异常", e);
                }
            }
        }
        return null;
    }

    /**
     * 字节数组解压缩后返回字符串
     * 
     * @param b
     *            需要被解压的字节数组
     * @param encoding
     *            编码格式
     * @return 解压后的字符串
     */
    public static String uncompressToString(byte[] b, String encoding) {
        if (b == null || b.length == 0) {
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(b);

        try {
            GZIPInputStream gunzip = new GZIPInputStream(in);
            byte[] buffer = new byte[BUFFER];
            int n;
            while ((n = gunzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
            return out.toString(encoding);
        } catch (IOException e) {
            LOG.error("GZipUtils uncompressToString(byte[] b, String encoding)方法抛出IO异常", e);
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils uncompressToString(byte[] b, String encoding)方法抛出IO异常", e);
                }
            }
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    LOG.error("GZipUtils uncompressToString(byte[] b, String encoding)方法抛出IO异常", e);
                }
            }
        }
        return null;
    }

}
